import React, { useRef, useState, useEffect } from 'react';
import PropTypes from 'prop-types';
import { PORT_RE, IP_RE } from '@util/constants';
import * as API from '@api/syslog';
import './index.less';
import {
  Form,
  Input,
  Button,
  message,
  Checkbox,
  Switch,
  Radio,
  Icon,
  Upload,
  Popconfirm
} from 'antd';

const prefixCls = 'syslog-config';
const { Item: FormItem } = Form;

const formItemLayout = {
  labelCol: {
    span: 5
  },
  wrapperCol: {
    span: 19
  }
};

function SyslogConfig(props) {
  const { validateFields, getFieldDecorator, setFieldsValue } = props.form;
  const [isLoading, setIsLoading] = useState(false); // 按钮loading
  const [isRunning, setIsRunning] = useState(false); // 是否启用
  const [isTLS, setIsTLS] = useState(false); // 是否启用TLS协议
  const [protocol, setProtocol] = useState('TCP'); // 协议
  const prevConfig = useRef(null);
  useEffect(() => {
    /* eslint-disable no-use-before-define*/
    getAndRenderSyslogConfig();
  }, []);

  // 外层文件对象缓存
  const fileListCache = {
    ca: null,
    cert: null,
    key: null
  };

  const toggleRunning = () => setIsRunning(!isRunning);

  const toggleTLS = () => setIsTLS(!isTLS);

  const renderConfig = config => {
    const { running, host, port, protocol, tls_auth } = config;
    running && setIsRunning(running);
    host && setFieldsValue({ host: '数据地址' });
    port && setFieldsValue({ port: '数据port' });
    protocol && setProtocol('UDP');
    tls_auth && setIsTLS(tls_auth);
  };

  const getAndRenderSyslogConfig = async () => {
    API.getSyslogConfig()
      .then(res => {
        const config = res?.data?.data?.syslog;
        prevConfig.current = config;
        renderConfig(config);
      })
      .catch(() => message.warn('获取syslog配置失败,请检查'));
  };

  const onProtocolChange = e => {
    const newProtocol = e.target.value;
    newProtocol === 'UDP' && setIsTLS(false);
    setProtocol(newProtocol);
  };
  // 有 开启/更新 syslog配置两种动作,用于进行动作判断(用于日志记录)
  const getActionCN = () => {
    return prevConfig.current.running ? '更新' : '开启';
  };

  //todo server接口联调
  const setSyslog = () => {
    setIsLoading(true);

    validateFields(async (errors, values) => {
      if (isTLS && !fileListCache.ca) {
        return message.error('请上传CA证书文件');
      }

      if (errors) {
        return message.error('校验不通过 保存配置失败');
      }

      const formData = new FormData();
      formData.append('host', values.host);
      formData.append('port', values.port);
      formData.append('protocol', protocol.toLowerCase());
      formData.append('tls_auth', isTLS);
      formData.append('actionCN', getActionCN());
      formData.append('ca_file', fileListCache.ca);
      formData.append('cert_file', fileListCache.cert);
      formData.append('key_file', fileListCache.key);

      API.setSyslogConfig(formData)
        .then(() => message.success('保存配置成功(功能暂无)'))
        .catch(() => message.warn('保存配置失败(功能暂无)'))
        .finally(() => setIsLoading(false));
    });
  };
  //todo server接口联调
  const stopSyslog = () => {
    setIsLoading(true);
    API.deleteSyslogConfig()
      .then(() => message.success('停用配置成功(功能暂无)'))
      .catch(() => message.warn('停用配置失败(功能暂无)'))
      .finally(() => setIsLoading(false));
  };

  const resetSyslog = () => {
    API.deleteSyslogConfig()
      .then(() => {
        getAndRenderSyslogConfig();
        message.success('停用配置成功(功能暂无)');
      })
      .catch(() => message.warn('停用配置失败(功能暂无)'));
  };

  const onClickSubmit = () => (isRunning ? setSyslog() : stopSyslog());

  const validatePort = component =>
    getFieldDecorator('port', {
      initialValue: 514,
      rules: [
        {
          required: true,
          message: '请填写指定端口'
        },
        {
          pattern: PORT_RE,
          message: '您输入的格式有误'
        }
      ]
    })(component);

  const validateHost = component =>
    getFieldDecorator('host', {
      rules: [
        {
          required: true,
          message: '请填写指定服务器地址'
        },
        {
          pattern: IP_RE,
          message: '您输入的格式有误'
        }
      ]
    })(component);

  const TopTip = () => (
    <div className={`${prefixCls}-tips`}>
      <Icon type="info-circle" theme="twoTone" twoToneColor="#fc8e49" />
      &nbsp; Syslog配置,通过指定日志外发服务器地址,发送系统生产的资产,任务,告警等日志
    </div>
  );

  const Uploader = ({ accept, label, fileType }) => {
    const LIMIT_SIZE = 1024 * 1024 * 20;
    const [fileList, setFileList] = useState([]);

    const checkFileAndSave = file => {
      const { size = 0 } = file;
      if (size === 0) {
        message.error('请确保您上传的文件内容不为空');
        return false;
      }
      if (size > LIMIT_SIZE) {
        message.error('该文件大小超过了限制（20M）');
        return false;
      }

      setFileList([file]);
      //这里将文件对象提升到外层缓存
      fileListCache[fileType] = file;
      return false;
    };

    return (
      <Upload
        className="uploader"
        accept={accept}
        fileList={fileList}
        beforeUpload={checkFileAndSave}
        onRemove={() => setFileList([])}
      >
        <Button>
          <Icon type="upload" />
          {label}
        </Button>
      </Upload>
    );
  };

  const InputsPlaceholder = () => (
    <>
      <div className={`${prefixCls}-placeholder`} />
      <div className={`${prefixCls}-placeholder`} />
      <div className={`${prefixCls}-placeholder`} />
    </>
  );

  return (
    <div className={prefixCls}>
      <div className={`${prefixCls}-page-title`}>Syslog配置</div>
      <div className={`${prefixCls}-top-box`}>
        <TopTip />
        <div className={`${prefixCls}-form`}>
          <Form labelAlign="left">
            <FormItem {...formItemLayout} label="启用" colon={false}>
              <Switch checked={isRunning} onChange={toggleRunning} />
            </FormItem>

            <FormItem {...formItemLayout} label="地址" colon={false}>
              {validateHost(<Input placeholder="请填写指定服务器地址" disabled={!isRunning} />)}
            </FormItem>

            <FormItem {...formItemLayout} label="端口" colon={false}>
              {validatePort(
                <Input placeholder="请填写指定端口,默认端口514" disabled={!isRunning} />
              )}
            </FormItem>

            <FormItem {...formItemLayout} label="协议" colon={false}>
              <Radio.Group onChange={onProtocolChange} value={protocol} disabled={!isRunning}>
                <Radio value={'UDP'}>UDP</Radio>
                <Radio value={'TCP'}>TCP</Radio>
              </Radio.Group>
            </FormItem>

            <FormItem {...formItemLayout} label="安全加密" colon={false}>
              <Checkbox
                checked={isTLS}
                onChange={toggleTLS}
                disabled={!(protocol === 'TCP') || !isRunning}
              >
                TLS(使用加密协议发送日志更安全,仅TCP)
              </Checkbox>
            </FormItem>

            {/* TLS选项开启时才需要输入这三个参数,否则渲染占位结构 */}
            {isTLS ? (
              <>
                <FormItem {...formItemLayout} label="CA" colon={false} required>
                  <Uploader label="请上传CA证书文件" fileType="ca" />
                </FormItem>

                <FormItem {...formItemLayout} label="证书" colon={false}>
                  <Uploader accept=".lic" label="请上传证书文件" fileType="cert" />
                </FormItem>

                <FormItem {...formItemLayout} label="私钥" colon={false}>
                  <Uploader accept=".txt" label="请上传私钥文件" fileType="key" />
                </FormItem>
              </>
            ) : (
              InputsPlaceholder()
            )}

            <FormItem {...formItemLayout} label={''} colon={false}>
              <Popconfirm
                title="删除范围是平台所有登录、操作日志。确认删除吗？"
                onConfirm={resetSyslog}
                placement="bottomRight"
                okText="确认"
                cancelText="取消"
              >
                <Button type="danger" className={`${prefixCls}-form-btn button-forwards`}>
                  重置
                </Button>
              </Popconfirm>
              <Button
                type="primary"
                loading={isLoading}
                className={`${prefixCls}-form-btn button-forwards`}
                onClick={onClickSubmit}
              >
                保存修改
              </Button>
            </FormItem>
          </Form>
        </div>
      </div>
    </div>
  );
}

SyslogConfig.propTypes = {
  form: PropTypes.object,
  accept: PropTypes.string,
  label: PropTypes.string,
  fileType: PropTypes.string
};

export default Form.create()(SyslogConfig);
